package cn.edu.lingnan.service.impl;

import cn.edu.lingnan.context.BaseContext;
import cn.edu.lingnan.mapper.PaperMapper;
import cn.edu.lingnan.mapper.StatisticsMapper;
import cn.edu.lingnan.service.StatisticsService;
import cn.edu.lingnan.user.Statistics.*;
import cn.edu.lingnan.user.dtos.UserStatisticsRequestDTO;
import cn.edu.lingnan.user.pojos.ExamedPaper;
import cn.edu.lingnan.user.pojos.Question;
import cn.edu.lingnan.user.pojos.UserAnswer;
import cn.edu.lingnan.user.pojos.UserExam;
import cn.edu.lingnan.user.vos.*;
import cn.edu.lingnan.utils.AiJudgementUtils;
import cn.edu.lingnan.utils.ConnectionCounter;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class StatisticsServiceImpl implements StatisticsService {
    @Autowired
    private StatisticsMapper statisticsMapper;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private PaperMapper paperMapper;

    @Autowired
    private ConnectionCounter connectionCounter;

    @Autowired
    AiJudgementUtils aiJudgementUtils;
    @Override
    @Transactional
    public void gradeAllEndedExams() {
        // 1. 获取所有已结束的考试ID
        List<Integer> endedExamIds = statisticsMapper.getEndedExamIds();
        if (endedExamIds.isEmpty()) {
            log.info("没有已结束的考试需要批阅。");
            return;
        }

        // 2. 获取所有已提交的用户考试记录
        List<UserExam> userExams = statisticsMapper.getSubmittedUserExams(endedExamIds);
        if (userExams.isEmpty()) {
            log.info("没有已提交的用户考试记录需要批阅。");
            return;
        }

        // 3. 收集所有题目ID
        Set<Integer> allQuestionIds = new HashSet<>();
        for (UserExam ue : userExams) {
            String answersJson = ue.getAnswers();
            if (answersJson == null || answersJson.trim().isEmpty()) {
                log.warn("UserExam ID {} 的 answers 字段为空，跳过该记录。", ue.getId());
                continue;
            }
            try {
                List<UserAnswer> answers = objectMapper.readValue(answersJson,
                        new TypeReference<List<UserAnswer>>() {});
                for (UserAnswer ans : answers) {
                    if (ans.getQuestionId() != null) {
                        allQuestionIds.add(ans.getQuestionId());
                    } else {
                        log.warn("UserExam ID {} 中存在 questionId 为 null 的答案，忽略。", ue.getId());
                    }
                }
            } catch (Exception e) {
                log.error("解析 UserExam ID {} 的 answers 时发生异常，跳过该记录。", ue.getId(), e);
            }
        }

        if (allQuestionIds.isEmpty()) {
            log.info("没有有效的题目ID需要批阅。");
            return;
        }

        // 4. 获取所有题目的详情
        List<Question> questions = statisticsMapper.getQuestionsByIds(new ArrayList<>(allQuestionIds));
        if (questions.isEmpty()) {
            log.warn("未找到任何与题目ID匹配的题目，无法进行评分。");
            return;
        }

        Map<Integer, Question> questionMap = questions.stream()
                .collect(Collectors.toMap(Question::getQuestionId, q -> q));

        // 5. 遍历每个用户考试记录，进行评分
        for (UserExam ue : userExams) {
            String answersJson = ue.getAnswers();
            if (answersJson == null || answersJson.trim().isEmpty()) {
                // 记录已在前面跳过
                continue;
            }

            List<UserAnswer> answers;
            try {
                answers = objectMapper.readValue(answersJson, new TypeReference<List<UserAnswer>>() {});
            } catch (Exception e) {
                log.error("再次解析 UserExam ID {} 的 answers 时发生异常，跳过该记录。", ue.getId(), e);
                continue;
            }

            double singleChoiceScore = 0.0;
            double multiChoiceScore = 0.0;
            double trialScore = 0.0;
            double fillScore = 0.0;
            double expoundScore = 0.0;
            double totalScore = 0.0;

            for (UserAnswer ua : answers) {
                if (ua.getQuestionId() == null) {
                    log.warn("UserExam ID {} 中存在 questionId 为 null 的答案，忽略。", ue.getId());
                    continue;
                }

                Question question = questionMap.get(ua.getQuestionId());
                if (question == null) {
                    log.warn("Question ID {} 未找到对应的题目，UserExam ID {} 跳过该题目。", ua.getQuestionId(), ue.getId());
                    continue;
                }

                int type = question.getQuestionType();
                String correctAnswer = question.getCorrectAnswer();
                Object userAnswer = ua.getAnswer();
                double score = 0.0; // 本题得分

                switch (type) {
                    case 1: // 单选题
                        if (userAnswer instanceof String) {
                            if (((String) userAnswer).trim().equalsIgnoreCase(correctAnswer.trim())) {
                                score = question.getQuestionScore();
                            }
                        }
                        singleChoiceScore += score;
                        break;

                    case 2: // 多选题
                        if (userAnswer instanceof List) {
                            List<String> userAnsList = (List<String>) userAnswer;
                            List<String> correctAnsList = Arrays.asList(correctAnswer.split(","));
                            Set<String> userAnsSet = userAnsList.stream()
                                    .map(String::trim)
                                    .map(String::toUpperCase)
                                    .collect(Collectors.toSet());
                            Set<String> correctAnsSet = correctAnsList.stream()
                                    .map(String::trim)
                                    .map(String::toUpperCase)
                                    .collect(Collectors.toSet());

                            // 检查是否包含任何错误选项
                            Set<String> incorrectOptions = new HashSet<>(userAnsSet);
                            incorrectOptions.removeAll(correctAnsSet);

                            if (!incorrectOptions.isEmpty()) {
                                // 包含错误选项，得零分
                                score = 0.0;
                            } else {
                                // 无错误选项，但可能未全选
                                if (userAnsSet.equals(correctAnsSet)) {
                                    // 全对，得满分
                                    score = question.getQuestionScore();
                                } else if (correctAnsSet.containsAll(userAnsSet) && !userAnsSet.isEmpty()) {
                                    // 部分对，给一半分(示例)
                                    score = question.getQuestionScore() / 2.0;
                                }
                            }
                        }
                        multiChoiceScore += score;
                        break;

                    case 3: // 判断题
                        if (userAnswer instanceof String) {
                            String userAnsStr = ((String) userAnswer).trim().toLowerCase();
                            String correctAnsStr = correctAnswer.trim().toLowerCase();
                            // 仅 "true"/"false" 并且与正确答案相同时给分
                            if ((userAnsStr.equals("true") || userAnsStr.equals("false"))
                                    && userAnsStr.equals(correctAnsStr)) {
                                score = question.getQuestionScore();
                            }
                        }
                        trialScore += score;
                        break;

                    case 4: // 填空题
                        if (userAnswer instanceof String) {
                            if (((String) userAnswer).trim().equalsIgnoreCase(correctAnswer.trim())) {
                                score = question.getQuestionScore();
                            }
                        }
                        fillScore += score;
                        break;

                    case 5: // 简答题（调用 AI ）
                        if (userAnswer instanceof String) {
                            try {
                                // questionName: 题目
                                // userAnswer: 考生答案
                                // correctAnswer: 标准答案
                                // questionScore: 分值(转为字符串)

                                JSONObject aiResult = aiJudgementUtils.judgement(question.getQuestionName(), (String) userAnswer, correctAnswer, question.getQuestionScore());
                                // 调用 AI 判分
                                if (aiResult != null) {
                                    // 获取 AI 给的分数, 并限定不能超过本题总分或小于0
                                    double aiScore = aiResult.getDoubleValue("score");
                                    if (aiScore > question.getQuestionScore()) {
                                        aiScore = question.getQuestionScore();
                                    }
                                    if (aiScore < 0) {
                                        aiScore = 0.0;
                                    }
                                    // 给分
                                    log.warn("UserExam ID {}, Question ID {}. AI 判分结果: {}", ue.getId(), question.getQuestionId(), aiScore);
                                    score = aiScore;

                                    // 如果需要保存反馈信息，可在 userExam 或 userAnswer 中扩展字段
                                    String feedback = aiResult.getString("feedback");
                                    // 示例: ue.setAiFeedback(feedback);

                                } else {
                                    score = 0.0;
                                }
                            } catch (Exception e) {
                                log.error("AI判分失败: UserExam ID {}, Question ID {}. 异常: {}",
                                        ue.getId(), question.getQuestionId(), e.getMessage());
                                score = 0.0;
                            }
                        }
                        expoundScore += score;
                        log.warn("UserExam ID {}, Question ID {}. 简答题得分: {}", ue.getId(), question.getQuestionId(),expoundScore);
                        break;

                    default:
                        log.warn("未知的题目类型 {}，Question ID {}，UserExam ID {} 跳过该题目。",
                                type, question.getQuestionId(), ue.getId());
                        break;
                }

                totalScore += score;
            }

            // 6. 赋值并更新数据库
            ue.setSingleChoiceScore(singleChoiceScore);
            ue.setMultipleChoiceScore(multiChoiceScore);
            ue.setFillScore(fillScore);
            ue.setTrialScore(trialScore);
            ue.setExpoundScore(expoundScore);
            ue.setTotalScore(totalScore);

            try {
                statisticsMapper.updateUserExamScores(ue);
            } catch (Exception e) {
                log.error("更新 UserExam ID {} 的分数时发生异常。", ue.getId(), e);
            }
        }

        log.info("批阅完成，共处理 {} 条用户考试记录。", userExams.size());
    }


    @Override
    public ExamedPaper getExamedPaper(Integer paperId, Integer examId, Integer userId) {
        //获取试题
        List<QuestionSatisticsVo> questionSatisticsVo = statisticsMapper.statisticsPaeprInfo(paperId);

        PaperWithQuestionVo paperWithQuestionVo = paperMapper.getPaperWithQuestionVo(paperId);

        for (QuestionSatisticsVo satisticsVo : questionSatisticsVo) {
            switch (satisticsVo.getQuestionType()) {
                case 1:
                    paperWithQuestionVo.setSingleChoiceScore(satisticsVo.getTotalScore());
                    break;
                case 2:
                    paperWithQuestionVo.setMultipleChoiceScore(satisticsVo.getTotalScore());
                    break;
                case 3:
                    paperWithQuestionVo.setTrialScore(satisticsVo.getTotalScore());
                    break;
                case 4:
                    paperWithQuestionVo.setFillScore(satisticsVo.getTotalScore());
                    break;
                case 5:
                    paperWithQuestionVo.setExpoundScore(satisticsVo.getTotalScore());
                    break;
            }

        }

        if (paperWithQuestionVo == null) {
            return null;
        }
        //查询用户答案和得分
        if(userId == null){
            userId = BaseContext.getCurrentId();
        }


        ExamedPaper userData = statisticsMapper.getUsersAnswer(examId, userId);


        if (userData == null) {
            return null;
        }
        userData.setPaperWithQuestionVo(paperWithQuestionVo);
        return  userData;

    }

    @Override
    public PaperSatisticsVo statisticsScore(Integer examId, Integer paperId) {
        // 查询当前用户的考试信息
        PaperSatisticsVo statisticsVo = statisticsMapper.statisticsScore(examId, BaseContext.getCurrentId());

        if (statisticsVo == null) {
            // 如果 statisticsVo 为 null，可以选择抛出自定义异常或返回特定的错误信息

             return null;
        }

        // 查询试卷信息
        List<QuestionSatisticsVo> questionSatisticsVo = statisticsMapper.statisticsPaeprInfo(paperId);
        if (questionSatisticsVo == null) {
            // 返回空值或抛出异常
            return null;
        }

        statisticsVo.setQuestionSatisticsVos(questionSatisticsVo);

        return statisticsVo;
    }


    @Override
    public ExamScoreStatsVO getExamScoreStats(Integer examId) {
        return statisticsMapper.getExamScoreStats(examId);
    }

    @Override
    public ScoreDistributionVO getScoreDistribution(Integer examId) {
        return statisticsMapper.getScoreDistribution(examId);
    }

    @Override
    public List<UserExamScoreVO> getTop3AnswerSheets(Integer examId) {
        return statisticsMapper.getTop3AnswerSheets(examId);
    }

    @Override
    public List<UserExamScoreVO> getWorst3AnswerSheets(Integer examId) {
        return statisticsMapper.getWorst3AnswerSheets(examId);
    }

    /**
     * 将四个查询组合为一个返回对象
     */
    @Override
    public ExamAllStatsVO getAllExamStats(Integer examId) {
        ExamAllStatsVO vo = new ExamAllStatsVO();
        // (a)
        vo.setScoreStats(getExamScoreStats(examId));
        // (b)
        vo.setScoreDistribution(getScoreDistribution(examId));
        // (c)
        vo.setTop3AnswerSheets(getTop3AnswerSheets(examId));
        // (d)
        vo.setWorst3AnswerSheets(getWorst3AnswerSheets(examId));
        return vo;
    }

    @Override
    public void ReviewExamedPaper(UserExam userExam) {
         statisticsMapper.ReviewExamedPaper(userExam);
    }

    @Override
    public UserStatisticsVO getUserStatistics(UserStatisticsRequestDTO requestDTO) {
        String date = requestDTO.getDate();
        String period = requestDTO.getPeriod() != null ? requestDTO.getPeriod() : "week"; // 默认按周统计
        UserStatisticsVO userStatistics = statisticsMapper.getUserStatistics(date, period);
        userStatistics.setOnlineCount(connectionCounter.getActiveConnections());
        return userStatistics;
    }

    @Override
    public void saveDiagnosis(Integer examId, Integer currentId, String diagnosis) {
         statisticsMapper.saveDiagnosis(examId, currentId, diagnosis);
    }




    //下面是管理员统计service

    @Override
    public List<TopStudentVO> getTopStudents() {
        return statisticsMapper.selectTopStudents();
    }

    @Override
    public List<ScoreRangeVO> getScoreRanges() {
        return statisticsMapper.selectScoreRanges();
    }

    @Override
    public List<ExamPerformanceVO> getBestExams() {
        return statisticsMapper.selectBestExams();
    }

    @Override
    public List<ExamPerformanceVO> getWorstExams() {
        return statisticsMapper.selectWorstExams();
    }

    @Override
    public List<AverageScoreTrendVO> getAverageScoreTrend() {
        return statisticsMapper.selectAverageScoreTrend();
    }

}
